home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / xlib / zrgb_pup.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  17KB  |  543 lines

  1. /*
  2.  * Copyright (c) 1994, Silicon Graphics, Inc.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee, provided
  6.  * that the name of Silicon Graphics may not be used in any advertising or
  7.  * publicity relating to the software without the specific, prior written
  8.  * permission of Silicon Graphics.
  9.  *
  10.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  11.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  12.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  13.  *
  14.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  15.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
  16.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE
  17.  * POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN
  18.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19.  *
  20.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  21.  */
  22. /*
  23.  *   zrgbmenu.c:
  24.  *
  25.  *    OpenGL-Xlib doublebuffered-RGB, depth-buffering, pop-up menu examp
  26.  *
  27.  *              zrgbmenu is the openGL "after" version of the IrisGL
  28.  *              "before" program, ~4Dgifts/examples/grafix/zrgbmenu.c
  29.  * 
  30.  *  It further implements--either manually via LEFTMOUSE, or in an
  31.  *  "automatic" (i.e. animation) mode format--movement of the polygons 
  32.  *  via compound rotations to allow for continuous screen-oriented 
  33.  *  rotations (see orient(), spin(), and drawScene() below).  Horizontal
  34.  *  mouse movement rotates the polygons about the y-axis where right is 
  35.  *  positive and left is negative.  Vertical mouse movement rotates the
  36.  *  polygons about the x-axis where down is positive and up is negative.
  37.  *
  38.  *                                            ratman - 1989
  39.  *                                                     1994, ported to OpenGL
  40.  */
  41. #include <GL/glx.h>
  42. #include <GL/glu.h>
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <X11/Xlib.h>
  46. #include <X11/Xutil.h>
  47. #include <X11/keysym.h>
  48.  
  49. #include "pup.h"
  50.  
  51. #define TRUE            1
  52. #define FALSE           0
  53.  
  54. /* Modes the program can be in */
  55. #define NOTHING 0
  56. #define ORIENT  1
  57. #define SPIN    2
  58.  
  59. /* Values returned from popup menu */
  60. #define MANUAL    1
  61. #define AUTOMATIC 2
  62. #define EXIT      3
  63.  
  64.  
  65. Display *dpy;                                    /* The X server connection */
  66. Atom del_atom;                                   /* WM_DELETE_WINDOW atom   */
  67. Window glwin;                                    /* handle to the GL window */
  68. XEvent event;
  69.  
  70. /* function declarations */
  71.  
  72. static void openwindow(char *);
  73. static void resize_buffer(void);
  74. static void clean_exit(void);
  75. void initGL(void);
  76. void orient(void);
  77. void update_scene(void);
  78. void spin(void);
  79. void drawScene(void);
  80. void drawPolys(void);
  81.  
  82. static float objmat[16] = {
  83.          1.0, 0.0, 0.0, 0.0,
  84.          0.0, 1.0, 0.0, 0.0,
  85.          0.0, 0.0, 1.0, 0.0,
  86.          0.0, 0.0, 0.0, 1.0,
  87. };
  88.  
  89. int xsize, ysize;                        /* current size-of-window keepers */
  90. long buffermode;          /* flag tracks current window (single or double) */
  91. int xpos, ypos, oxpos, oypos;                /* old and new mouse position */
  92.  
  93. int mode = 0;
  94. int menu;
  95. int omx, mx, omy, my;                         /* old and new mouse position */
  96. float scrnaspect;                             /* aspect ratio value         */
  97.  
  98. main(argc, argv)
  99. int argc;
  100. char *argv[];
  101. {
  102.     int myExpose, myConfigure, myButtPress, myKeyPress;
  103.     int needToDraw = 0;                  /* don't set this to true until
  104.                                              we get our first Expose event */
  105.     long menuval;
  106.  
  107.  
  108.     myExpose = myConfigure = myButtPress = myKeyPress = FALSE;
  109.  
  110.     openwindow(argv[0]);
  111.  
  112.     initGL();                                          /* do GL init stuff */
  113.  
  114.     /*
  115.      * The event loop.
  116.      */
  117.     while (1) {         /* standard logic:  get event(s), process event(s) */
  118.  
  119.  
  120.         XEvent event;
  121.         KeySym keysym;
  122.         char buf[4];
  123.  
  124.     /* this "do while" loop does the `get events' half of the "get events,
  125.      *  process events" action of the infinite while.  this is to ensure
  126.      *  the event queue is always drained before the events that have come
  127.      *  in are processed.
  128.      */
  129.     while (XPending(dpy)) {
  130.  
  131.             XNextEvent(dpy, &event);
  132.             switch (event.type) {
  133.  
  134.             /* "Expose" events are sort of like "REDRAW" in gl-speak in
  135.              *  terms of when a window becomes visible, or a previously
  136.              *  invisible part becomes visible.
  137.              */
  138.                 case Expose:                        /* Exposures */
  139.                     needToDraw = myExpose = TRUE;
  140.                     break;
  141.  
  142.             /* "ConfigNotify" events are like "REDRAW" in terms of changes
  143.              *   to a window's size or position.
  144.              */
  145.                 case ConfigureNotify:                /* Resize GL manually */
  146.                     xsize = event.xconfigure.width;
  147.                     ysize = event.xconfigure.height;
  148.                     needToDraw = myConfigure = TRUE;
  149.                     break;
  150.  
  151.             /* Wait for "MotionNotify" events so the queue doesn't fill up
  152.              */
  153.                 case MotionNotify:
  154.                     myButtPress = TRUE;
  155.                     xpos = event.xmotion.x;
  156.                     ypos = event.xmotion.y;
  157.             if (mode == ORIENT) {
  158.             update_scene();
  159.             needToDraw=TRUE;
  160.             }
  161.                     mode = ORIENT;
  162.                     break;
  163.  
  164.             /* "ButtonPress" events hail from the ButtonPressMask feed to
  165.              *   XCreateWindow via XSetWindowAttributes' event_mask field
  166.              */
  167.                 case ButtonPress:
  168.             if (event.xbutton.button == Button3) { /* RIGHTMOUSE:  */
  169.                         menuval = dopup(menu);
  170.                         switch(menuval) {
  171.                         case MANUAL:
  172.                             mode = NOTHING;
  173.                             break;
  174.                         case AUTOMATIC:
  175.                             mode = SPIN;
  176.                             needToDraw = TRUE;
  177.                             break;
  178.                         case EXIT:
  179.                             clean_exit();
  180.                             break;
  181.                         default:
  182.                             break;
  183.                     }
  184.                 }
  185.  
  186.             /* Wait for "ButtonRelease" events so the queue doesn't fill up
  187.              *  the way it wud if the user sits on ButtonPresss.
  188.              */
  189.                 case ButtonRelease:
  190.                     if (event.xbutton.button == Button1)     /* LEFTMOUSE:  */
  191.                         mode = NOTHING;                   /* switch back to */
  192.                     break;                                /* "manual" mode  */
  193.                      
  194.             /* "ClientMessage" is generated if the WM itself is being
  195.              *  gunned down and sends an exit signal to any running prog.
  196.              */
  197.                 case ClientMessage:
  198.                     if (event.xclient.data.l[0] == del_atom)
  199.                         clean_exit();
  200.                     break;
  201.  
  202.             /* "KeyPress" events are those that would be generated before
  203.              *   whenever queueing up any KEYBD key via qdevice.
  204.              */
  205.                 case KeyPress:
  206.                    /* save out which unmodified key (i.e. the  key was
  207.                     *  not modified w/something like "Shift", "Ctrl",
  208.                     *  or "Alt") got pressed for use below.
  209.                     */
  210.                     XLookupString((XKeyEvent *)&event, buf, 4, &keysym, 0);
  211.                     myKeyPress = TRUE;
  212.                     break;
  213.  
  214.                 default:
  215.                     break;
  216.  
  217.             }  /* end switch (event.type) */
  218.  
  219.  
  220.     }
  221.  
  222.     /* On an "Expose" event, redraw the affected pop'd or de-iconized window
  223.      */
  224.         if (myExpose) {
  225.             resize_buffer();
  226.             myExpose = FALSE;               /* reset flag--queue now empty */
  227.         }
  228.  
  229.     /* On a "ConfigureNotify" event, the GL window has either been moved or
  230.      *  resized.  Respond accordingly and then redraw its contents.
  231.      */
  232.         if (myConfigure) {
  233.             oxpos = xpos;
  234.             oypos = ypos;
  235.             resize_buffer();
  236.             myConfigure = FALSE;            /* reset flag--queue now empty */
  237.         }
  238.  
  239.         if (needToDraw) {
  240.             if (mode == SPIN) {
  241.                 update_scene();
  242.                 drawScene();
  243.                 /*
  244.                  * Note: Don't reset needToDraw, so we keep on
  245.                  * spinning.
  246.                  */
  247.             } else {
  248.                 drawScene();
  249.                 needToDraw = FALSE;
  250.             }
  251.         }
  252.  
  253.         /* On a keypress of Esc key, exit program.
  254.          */
  255.         if (myKeyPress) {
  256.             if (keysym == XK_Escape)
  257.                 clean_exit();
  258.         }
  259.  
  260.         if (myButtPress) {
  261.             orient();
  262.             drawScene();
  263.             myButtPress = FALSE;
  264. /*
  265.             mode = NOTHING;
  266. */
  267.         }
  268.     }      /* end while(1) */
  269.  
  270. }      /* end main */
  271.  
  272.  
  273.  
  274.  
  275. static int attributeList[] = { GLX_RGBA,
  276.                                GLX_DOUBLEBUFFER,
  277.                                GLX_RED_SIZE, 1,
  278.                                GLX_GREEN_SIZE, 1,
  279.                                GLX_BLUE_SIZE, 1,
  280.                                GLX_DEPTH_SIZE, 1,
  281.                                None };
  282. static int attributeList2[] = { GLX_RGBA,
  283.                                GLX_RED_SIZE, 1,
  284.                                GLX_GREEN_SIZE, 1,
  285.                                GLX_BLUE_SIZE, 1,
  286.                                GLX_DEPTH_SIZE, 1,
  287.                                None };
  288.  
  289. static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
  290.     return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
  291. }
  292.  
  293. /*  openwindow -
  294.  *     establish connection to X server, get screen info, specify the
  295.  *     attributes we want the WM to try to provide, and create the GL window
  296.  */
  297. static void openwindow(char *progname) {
  298.  
  299.     XVisualInfo *vi;
  300.     GLXContext cx;
  301.     Colormap cmap;
  302.     XSizeHints Winhints;                          /* used to fix window size */
  303.     XSetWindowAttributes swa;
  304.     int scrnnum;                               /* X screen number            */
  305.     int xorig, yorig;                          /* window (upper-left) origin */
  306.     long scrnwidth, scrnheight;
  307.  
  308.  
  309.  
  310.  
  311.    /* define window initial size */
  312.     xorig = 50;  yorig = 40;
  313.     xsize = 300; ysize = 240;
  314.  
  315.    /* Connect to the X server and get screen info */
  316.     if ((dpy = XOpenDisplay(NULL)) == NULL) {
  317.         fprintf(stderr, "%s: cannot connect to X server %s\n",
  318.                                  progname, XDisplayName(NULL));
  319.         exit(1);
  320.     }
  321.  
  322.     scrnnum = DefaultScreen(dpy);
  323.     scrnwidth = DisplayWidth(dpy, scrnnum);
  324.     scrnheight = DisplayHeight(dpy, scrnnum);
  325.  
  326.     /* Code to keep same aspec ratio as the screen */
  327.     scrnaspect = ((float)scrnwidth)/((float)scrnheight);
  328.  
  329.         /* get an appropriate visual */
  330.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
  331.     if (vi == NULL) {
  332.         fprintf(stderr, "Unable to obtain Doublebuffered visual;  ");
  333.         fprintf(stderr, "now going for singlebuffer'd...\n");
  334.         vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList2);
  335.     }
  336.     if (vi == NULL) {
  337.         printf("Unable to obtain Singlebuffered VISUAL(????)\n");
  338.         exit(0);
  339.     }
  340.  
  341.     /* create GLX context */
  342.     cx = glXCreateContext(dpy, vi, None, GL_TRUE);
  343.  
  344.     /* create a colormap */
  345.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
  346.                            vi->visual, AllocNone);
  347.  
  348.     /* create a window */
  349.     swa.colormap = cmap;
  350.     swa.border_pixel = 0;
  351.     swa.event_mask = StructureNotifyMask  | ButtonPressMask | ButtonReleaseMask
  352.                         | ExposureMask | Button1MotionMask | KeyPressMask;  
  353.     glwin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
  354.                           xorig, yorig, xsize, ysize,
  355.                           0, vi->depth, InputOutput, vi->visual,
  356.                           CWBorderPixel|CWColormap|CWEventMask, &swa);
  357.  
  358.     XMapWindow(dpy, glwin);
  359.     XIfEvent(dpy, &event, WaitForNotify, (char*)glwin);
  360.  
  361.     /* connect the context to the window */
  362.     glXMakeCurrent(dpy, glwin, cx);
  363.  
  364.     if (!(glwin)) {
  365.         fprintf(stderr,"%s: couldn't create \"parent\" X window\n",progname);
  366.         exit(1);
  367.     }
  368.  
  369.    /* define string that will show up in the window title bar (and icon) */
  370.     XStoreName(dpy, glwin, "rgb depth/dbl -buffered pop-up menu prog");
  371.  
  372.  
  373.    /* specify the values for the Window Size Hints we want to enforce:  this
  374.     *  window's aspect ratio needs to stay at 1:1, constrain min and max
  375.     *  window size, and specify the initial size of the window.
  376.     */
  377.     Winhints.width  = xsize;          /* specify desired x/y size of window */
  378.     Winhints.height = ysize;
  379.     Winhints.min_width = xorig;                       /* define min and max */
  380.     Winhints.max_width = scrnheight-1;                /* width and height   */
  381.     Winhints.min_height = yorig;
  382.     Winhints.max_height = scrnheight-1;
  383.     Winhints.min_aspect.x = scrnwidth;/* keep aspect to a scrnX:scrnY ratio */
  384.     Winhints.max_aspect.x = scrnwidth;
  385.     Winhints.min_aspect.y = scrnheight;
  386.     Winhints.max_aspect.y = scrnheight;
  387.     Winhints.flags = USSize|PMaxSize|PMinSize|PAspect;           /* set the */
  388.     XSetNormalHints(dpy, glwin, &Winhints);      /* corresponding flags */
  389.  
  390.    /* express interest in WM killing this app */
  391.     if ((del_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True)) != None)
  392.         XSetWMProtocols(dpy, glwin, &del_atom, 1);
  393.  
  394.     menu = defpup(dpy, scrnnum, 
  395.           "OGL RGB depth-bufr'd pup prog %t|Manual Mode|Automatic Mode|Exit");
  396.     return ;
  397. }
  398.  
  399.  
  400.  
  401. /*  window has been moved or resized so update viewport & CTM stuff.
  402.  */
  403. static void resize_buffer() {
  404.     scrnaspect = xsize / (double) ysize;
  405.     glViewport(0, 0, xsize-1, ysize-1);
  406. }
  407.  
  408.  
  409.  
  410. /*  clean up before exiting
  411.  */
  412. static void clean_exit(void)
  413. {
  414.     XCloseDisplay(dpy);
  415.     exit(0);
  416. }
  417.  
  418.  
  419.  
  420. /* setup all necessary GL initialzation parameters.
  421.  */
  422. void initGL(void)
  423. {
  424.     glEnable(GL_DEPTH_TEST);
  425.     glClearColor(0.16, 0.39, 0.78, 0.0);
  426.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  427.     glLoadIdentity();
  428.     gluPerspective(400.0, scrnaspect, 30.0, 600.0);
  429. }
  430.  
  431.  
  432.  
  433. void update_scene(void) {
  434.  
  435.     switch (mode) {
  436.  
  437.         case ORIENT:
  438.             orient();
  439.             break;
  440.         case SPIN:
  441.             spin();
  442.             break;
  443.     }
  444. }
  445.  
  446.  
  447. void orient(void)
  448. {
  449.     float dx, dy;
  450.  
  451.     glPushMatrix();
  452.     dx = 0.01 * (xpos-oxpos);
  453.     dy = 0.01 * (oypos-ypos);
  454.     glLoadIdentity();
  455.     glRotatef(dx, 1.0, 0.0, 0.0);
  456.     glRotatef(dy, 0.0, 1.0, 0.0);
  457.     glMultMatrixf(objmat);
  458.     glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
  459.  
  460.     glPopMatrix();
  461. }
  462.  
  463.  
  464.  
  465. void spin (void) {
  466.  
  467.     glPushMatrix();
  468.  
  469.     glLoadIdentity();
  470.  
  471.     glRotatef(2.5, 1.0, 0.0, 0.0);            
  472.     glRotatef(3.0, 0.0, 1.0, 0.0);           
  473.     glRotatef(2.0, 0.0, 0.0, 1.0);          
  474.  
  475.     glMultMatrixf(objmat);
  476.     glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
  477.  
  478.     glPopMatrix();
  479.  
  480. }
  481.  
  482.  
  483. void drawScene(void)
  484. {
  485.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  486.  
  487.     glLoadIdentity();
  488.     gluPerspective(400.0, scrnaspect, 30.0, 600.0);
  489.     glTranslatef(0.0, 0.0, -40.0);
  490.     glMultMatrixf(objmat);
  491.     glRotatef(-400.0, 0.0, 1.0, 0.0); /* skews orig view to show all polys */
  492.     drawPolys();
  493.     glXSwapBuffers(dpy, glwin);
  494. }
  495.  
  496.  
  497.  
  498. float polygon1[3][3] = { {-10.0, -10.0,   0.0,},
  499.                          { 10.0, -10.0,   0.0,},
  500.                          {-10.0,  10.0,   0.0,} };
  501.  
  502. float polygon2[3][3] = { {  0.0, -10.0, -10.0,},
  503.                          {  0.0, -10.0,  10.0,},
  504.                          {  0.0,   5.0, -10.0,} };
  505.  
  506. float polygon3[4][3] = { {-10.0,   6.0,   4.0,},
  507.                          {-10.0,   3.0,   4.0,},
  508.                          {  4.0,  -9.0, -10.0,},
  509.                          {  4.0,  -6.0, -10.0,} };
  510.  
  511. void drawPolys(void) {
  512.  
  513.     glBegin(GL_POLYGON);
  514.     glColor4f(0.0, 0.0, 0.0, 0.0);
  515.     glVertex3fv(&polygon1[0][0]);
  516.     glColor4f(0.5, 0.5, 0.5, 0.0);
  517.     glVertex3fv(&polygon1[1][0]);
  518.     glColor4f(1.0, 1.0, 1.0, 0.0);
  519.     glVertex3fv(&polygon1[2][0]);
  520.     glEnd();
  521.  
  522.     glBegin(GL_POLYGON);
  523.     glColor4f(1.0, 1.0, 0.0, 0.0);
  524.     glVertex3fv(&polygon2[0][0]);
  525.     glColor4f(0.0, 1.0, 0.5, 0.0);
  526.     glVertex3fv(&polygon2[1][0]);
  527.     glColor4f(0.0, 0.0, 1.0, 0.0);
  528.     glVertex3fv(&polygon2[2][0]);
  529.     glEnd();
  530.  
  531.     glBegin(GL_POLYGON);
  532.     glColor4f(1.0, 1.0, 0.0, 0.0);
  533.     glVertex3fv(&polygon3[0][0]);
  534.     glColor4f(1.0, 0.0, 1.0, 0.0);
  535.     glVertex3fv(&polygon3[1][0]);
  536.     glColor4f(0.0, 0.0, 1.0, 0.0);
  537.     glVertex3fv(&polygon3[2][0]);
  538.     glColor4f(1.0, 0.0, 1.0, 0.0);
  539.     glVertex3fv(&polygon3[3][0]);
  540.     glEnd();
  541.  
  542. }
  543.